/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 - 2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/

package com.genia.toolbox.web.gwt.form.client.widget;

import com.genia.toolbox.web.gwt.form.client.form.SortableMultipleItem;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * a {@link VerticalPanel} that allow its element to be sorted.
 */
public class SortableVerticalPanel
    extends VerticalPanel
{

  /**
   * the parent widget.
   */
  private final SortableWidget parentWidget;

  /**
   * the {@link SortableMultipleItem} that allow to configure this widget.
   */
  private final SortableMultipleItem sortableMultipleItem;



  /**
   * constructor.
   * 
   * @param parentWidget
   *          the {@link SortableMultipleItem} that allow to configure this
   *          widget.
   */
  public SortableVerticalPanel(SortableWidget parentWidget)
  {
    this.parentWidget = parentWidget;
    this.sortableMultipleItem = (SortableMultipleItem) parentWidget.getItem();
  }



  /**
   * update the sort controls of the elements of the panel.
   */
  private void updateSortControls()
  {
    final int lastElementIndex = getWidgetCount() - 1;
    if (lastElementIndex < 0) {
      return;
    }
    WidgetWithSortButtons firstElement = ((WidgetWithSortButtons) super.getWidget(0));
    WidgetWithSortButtons lastElement = ((WidgetWithSortButtons) super.getWidget(lastElementIndex));
    if (lastElementIndex >= 0) {
      firstElement.setFirstElement(true);
      lastElement.setLastElement(true);
    }
    if (lastElementIndex > 0) {
      WidgetWithSortButtons secondElement = ((WidgetWithSortButtons) super.getWidget(1));
      WidgetWithSortButtons nextToLastElement = ((WidgetWithSortButtons) super.getWidget(lastElementIndex - 1));
      lastElement.setFirstElement(false);
      firstElement.setLastElement(false);
      secondElement.setFirstElement(false);
      nextToLastElement.setLastElement(false);
    }
  }



  /**
   * move the widget at the given index to the given position.
   * 
   * @param oldIndex
   *          the index of the widget to move
   * @param newIndex
   *          the new index of the widget
   */
  void moveWidget(int oldIndex, int newIndex)
  {
    Widget widgetToMove = super.getWidget(oldIndex);
    super.remove(widgetToMove);
    super.insert(widgetToMove, newIndex);
    parentWidget.moveValue(oldIndex, newIndex);
    updateSortControls();
  }



  /**
   * gets the widget at the given index.
   * 
   * @param index
   *          the index to be retrieved
   * @return the widget at the specified index
   * @see com.google.gwt.user.client.ui.ComplexPanel#getWidget(int)
   */
  @Override
  public Widget getWidget(int index)
  {
    if (sortableMultipleItem.isSortable()) {
      return ((WidgetWithSortButtons) super.getWidget(index)).getBaseWidget();
    }
    else {
      return super.getWidget(index);
    }
  }



  /**
   * gets the index of the specified widget.
   * 
   * @param child
   *          the widget to be found
   * @return the index of the specified widget, or <code>-1</code> if it is
   *         not found
   * @see com.google.gwt.user.client.ui.ComplexPanel#getWidgetIndex(com.google.gwt.user.client.ui.Widget)
   */
  @Override
  public int getWidgetIndex(Widget child)
  {
    if (sortableMultipleItem.isSortable()) {
      if (child instanceof WidgetWithSortButtons) {
        return super.getWidgetIndex(child);
      }
      int result = 0;
      for (Widget widgetWithSortButtons : this) {
        if (((WidgetWithSortButtons) widgetWithSortButtons).getBaseWidget() == child) {
          return result;
        }
        result++;
      }
      return -1;
    }
    else {
      return super.getWidgetIndex(child);
    }
  }



  /**
   * Adds a child widget to the panel. If the Widget is already attached to the
   * VerticalPanel, it will be moved to the end of the panel.
   * 
   * @param widget
   *          the widget to be added
   * @see com.google.gwt.user.client.ui.VerticalPanel#add(com.google.gwt.user.client.ui.Widget)
   */
  @Override
  public void add(Widget widget)
  {
    if (sortableMultipleItem.isSortable()) {
      super.add(new WidgetWithSortButtons(this, widget));
      updateSortControls();
    }
    else {
      super.add(widget);
    }
  }



  /**
   * Inserts a widget before the specified index. If the Widget is already
   * attached to the VerticalPanel, it will be moved to the specified index.
   * 
   * @param widget
   *          the widget to be inserted
   * @param beforeIndex
   *          the index before which it will be inserted
   * @see com.google.gwt.user.client.ui.VerticalPanel#insert(com.google.gwt.user.client.ui.Widget,
   *      int)
   */
  @Override
  public void insert(Widget widget, int beforeIndex)
  {
    if (sortableMultipleItem.isSortable()) {
      super.insert(new WidgetWithSortButtons(this, widget), beforeIndex);
      updateSortControls();
    }
    else {
      super.insert(widget, beforeIndex);
    }
  }



  /**
   * Removes a child widget.
   * 
   * @param widget
   *          the widget to be removed
   * @return <code>true</code> if the widget was present
   * @see com.google.gwt.user.client.ui.VerticalPanel#remove(com.google.gwt.user.client.ui.Widget)
   */
  @Override
  public boolean remove(Widget widget)
  {
    if (sortableMultipleItem.isSortable()) {
      int widgetIndex = getWidgetIndex(widget);
      if (widgetIndex != -1) {
        super.remove(super.getWidget(widgetIndex));
        updateSortControls();
      }
      return widgetIndex != -1;
    }
    else {
      return super.remove(widget);
    }
  }



  /**
   * getter for the sortableMultipleItem property.
   * 
   * @return the sortableMultipleItem
   */
  SortableMultipleItem getSortableMultipleItem()
  {
    return sortableMultipleItem;
  }

}
